/*
 *  Vector2D.h
 *  Panel2D
 *
 *  Created by Gregor Veble on 8/15/07.
 *  Copyright 2007 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef VECTOR2D_H
#define VECTOR2D_H

#include "../math/mathematics.h"

struct Vector2D{
	re v[2];
};

struct Matrix2D{
	re m[2][2];
};

inline Vector2D e2d1(){
	Vector2D c;
	c.v[0]=ONE;
	c.v[1]=ZERO;
	return c;
}

inline Vector2D e2d2(){
	Vector2D c;
	c.v[0]=ZERO;
	c.v[1]=ONE;
	return c;
}

inline Vector2D e2di(const int i){
	if(i==0){
		return e2d1();
	} else {
		return e2d2();
	}
}

inline Vector2D v2d0(){
	Vector2D c;
	c.v[0]=ZERO;
	c.v[1]=ZERO;
	return c;
}

inline Vector2D operator+(const Vector2D a, const Vector2D b){
	Vector2D c;
	c.v[0]=a.v[0]+b.v[0];
	c.v[1]=a.v[1]+b.v[1];
	return c;
}

inline Vector2D operator-(const Vector2D a, const Vector2D b){
	Vector2D c;
	c.v[0]=a.v[0]-b.v[0];
	c.v[1]=a.v[1]-b.v[1];
	return c;
}

inline Vector2D operator*(const re a, const Vector2D b){
	Vector2D c;
	c.v[0]=a*b.v[0];
	c.v[1]=a*b.v[1];
	return c;
}

inline Vector2D operator*(const Vector2D b, const re a){
	Vector2D c;
	c.v[0]=a*b.v[0];
	c.v[1]=a*b.v[1];
	return c;
}
inline Vector2D operator/(const Vector2D b, const re d){
	Vector2D c;
	re a;
	
	if(d!=ZERO){
		a=ONE/d;
	} else {
		a=ZERO;
	}
	
	c.v[0]=a*b.v[0];
	c.v[1]=a*b.v[1];
	return c;
}

inline re operator*(const Vector2D a, const Vector2D b){
	return a.v[0]*b.v[0]+a.v[1]*b.v[1];
}

inline re Vectorial(const Vector2D a, const Vector2D b){
	return a.v[0]*b.v[1]-a.v[1]*b.v[0];
}

inline re Norm(const Vector2D a){
	return SQRT(a.v[0]*a.v[0]+a.v[1]*a.v[1]);
}

inline Vector2D Normalize(const Vector2D a){
	re n=Norm(a);
	if(n>ZERO){
		return a/n;
	} else {
		return e2d1();
	}
}

inline re Sqr(Vector2D a){
	return a.v[0]*a.v[0]+a.v[1]*a.v[1];
}

inline Matrix2D operator*(const Matrix2D a, const Matrix2D b){
	Matrix2D c;
	
	c.m[0][0]=a.m[0][0]*b.m[0][0]+a.m[0][1]*b.m[1][0];
	c.m[1][0]=a.m[1][0]*b.m[0][0]+a.m[1][1]*b.m[1][0];
	c.m[0][1]=a.m[0][0]*b.m[0][1]+a.m[0][1]*b.m[1][1];
	c.m[1][1]=a.m[1][0]*b.m[0][1]+a.m[1][1]*b.m[1][1];
	
	return c;
}

inline Matrix2D operator+(const Matrix2D a, const Matrix2D b){
	Matrix2D c;
	
	c.m[0][0]=a.m[0][0]+b.m[0][0];
	c.m[0][1]=a.m[0][1]+b.m[0][1];
	c.m[1][0]=a.m[1][0]+b.m[1][0];
	c.m[1][1]=a.m[1][1]+b.m[1][1];

	return c;
}


inline Vector2D operator*(const Matrix2D a, const Vector2D b){
	Vector2D c;
	
	c.v[0]=a.m[0][0]*b.v[0]+a.m[0][1]*b.v[1];
	c.v[1]=a.m[1][0]*b.v[0]+a.m[1][1]*b.v[1];
	
	return c;
}

inline Matrix2D operator*(const re a, const Matrix2D b){
	Matrix2D c;
	
	c.m[0][0]=a*b.m[0][0];
	c.m[0][1]=a*b.m[0][1];
	c.m[1][0]=a*b.m[1][0];
	c.m[1][1]=a*b.m[1][1];
	
	return c;
}

inline Matrix2D Transpose(const Matrix2D a){
	Matrix2D c;
	
	c.m[0][0]=a.m[0][0];
	c.m[0][1]=a.m[1][0];
	c.m[1][0]=a.m[0][1];
	c.m[1][1]=a.m[0][0];
	
	return c;
}

inline Matrix2D Tensorial(const Vector2D a, const Vector2D b){
	Matrix2D c;
	
	c.m[0][0]=a.v[0]*b.v[0];
	c.m[0][1]=a.v[0]*b.v[1];
	c.m[1][0]=a.v[1]*b.v[0];
	c.m[1][1]=a.v[1]*b.v[1];
	
	return c;
	
}

#endif
